package cn.tlxqc.jsonwebtoken.common.filter;

import cn.tlxqc.jsonwebtoken.common.constants.Constants;
import cn.tlxqc.jsonwebtoken.common.enums.ResultEnum;
import cn.tlxqc.jsonwebtoken.common.sign.Audience;
import cn.tlxqc.jsonwebtoken.common.utils.JwtHelper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtHandler;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.filter.GenericFilterBean;

import javax.security.auth.login.LoginException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Component
public class JwtFilter extends GenericFilterBean {

    @Autowired
    private Audience audience;


    private static List<String> EXCLUDE = Arrays.asList(new String[]{"/login"});
    /**
     * Reserved claims（保留），它的含义就像是编程语言的保留字一样，属于JWT标准里面规定的一些claim。JWT标准里面定好的claim有：
     *
     *      iss(Issuser)：代表这个JWT的签发主体；
     *      sub(Subject)：代表这个JWT的主体，即它的所有人；
     *      aud(Audience)：代表这个JWT的接收对象；
     *      exp(Expiration time)：是一个时间戳，代表这个JWT的过期时间；
     *      nbf(Not Before)：是一个时间戳，代表这个JWT生效的开始时间，意味着在这个时间之前验证JWT是会失败的；
     *      iat(Issued at)：是一个时间戳，代表这个JWT的签发时间；
     *      jti(JWT ID)：是JWT的唯一标识。
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("============进行过滤=============");
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (EXCLUDE.contains(request.getServletPath())){
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }

        //等到请求头信息authorization信息
        final String authHeader = request.getHeader("authorization");

        if ("OPTIONS".equals(request.getMethod())){
            response.setStatus(HttpServletResponse.SC_OK);
            filterChain.doFilter(servletRequest,servletResponse);
        }else {
            if (authHeader == null || authHeader.startsWith("bearer;")){
                try {
                    throw new LoginException(ResultEnum.LOGIN_ERROR.getMsg());
                } catch (LoginException e) {
                    e.printStackTrace();
                }
            }

            final String token = authHeader.substring(7);

            try {
                if (audience == null){
                    BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
                    audience = (Audience) factory.getBean("audience");
                }
                final Claims claims = JwtHelper.parseJWT(token,audience.getBase64Secret());
                if(claims == null){
                    throw new LoginException(ResultEnum.LOGIN_ERROR.getMsg());
                }
                request.setAttribute(Constants.CLAIMS, claims);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    throw new LoginException(ResultEnum.LOGIN_ERROR.getMsg());
                } catch (LoginException e1) {
                    e1.printStackTrace();
                }
            }
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
}
